from typing import List

# SM3常量
IV = [
    0x7380166F, 0x4914B2B9, 0x172442D7, 0xDA8A0600,
    0xA96F30BC, 0x163138AA, 0xE38DEE4D, 0xB0FB0E4E
]

T_j = [0x79CC4519] * 16 + [0x7A879D8A] * 48

def rotate_left(x: int, n: int) -> int:
    n = n % 32
    return ((x << n) | (x >> (32 - n))) & 0xFFFFFFFF

def P0(x): return x ^ rotate_left(x, 9) ^ rotate_left(x, 17)
def P1(x): return x ^ rotate_left(x, 15) ^ rotate_left(x, 23)

def FF(x, y, z, j):
    return x ^ y ^ z if j < 16 else (x & y) | (x & z) | (y & z)
def GG(x, y, z, j):
    return x ^ y ^ z if j < 16 else (x & y) | (~x & z)

def sm3_compress(v_i: List[int], b_i: bytes) -> List[int]:
    W = [int.from_bytes(b_i[i*4:(i+1)*4], 'big') for i in range(16)]
    for j in range(16, 68):
        W.append(P1(W[j-16] ^ W[j-9] ^ rotate_left(W[j-3], 15)) ^ rotate_left(W[j-13], 7) ^ W[j-6])
    W_ = [W[j] ^ W[j+4] for j in range(64)]

    A, B, C, D, E, F, G, H = v_i
    for j in range(64):
        SS1 = rotate_left((rotate_left(A, 12) + E + rotate_left(T_j[j], j)) & 0xFFFFFFFF, 7)
        SS2 = SS1 ^ rotate_left(A, 12)
        TT1 = (FF(A, B, C, j) + D + SS2 + W_[j]) & 0xFFFFFFFF
        TT2 = (GG(E, F, G, j) + H + SS1 + W[j]) & 0xFFFFFFFF
        D = C
        C = rotate_left(B, 9)
        B = A
        A = TT1
        H = G
        G = rotate_left(F, 19)
        F = E
        E = P0(TT2)
    return [a ^ b for a, b in zip([A, B, C, D, E, F, G, H], v_i)]

def sm3_hash(msg: bytes) -> bytes:
    # 填充
    mlen = len(msg)
    padlen = (56 - (mlen + 1) % 64) % 64
    padded = msg + b'\x80' + b'\x00' * padlen + (mlen * 8).to_bytes(8, 'big')
    n = len(padded) // 64

    v = IV.copy()
    for i in range(n):
        v = sm3_compress(v, padded[i*64:(i+1)*64])
    return b''.join(x.to_bytes(4, 'big') for x in v)

if __name__ == '__main__':
    # 示例输入: 512位数据（64字节），如全0或全1或其它样例
    import binascii

    # 例2：自定义输入
    hexstr = "f93719cdf93719cdf93719cdf93719cdf93719cdf93719cdf93719cdf93719cdf93719cdf93719cdf93719cdf93719cdf93719cdf93719cdf93719cdf93719cd"
    data2 = bytes.fromhex(hexstr)
    digest2 = sm3_hash(data2)
    print("Input:", data2.hex())
    print("SM3 digest:", digest2.hex())